/*
 * 
 * 
 * 
 */
package com.hboxs.asl.qcloudLVB.service.impl;

import com.hboxs.asl.*;
import com.hboxs.asl.dao.CourseDao;
import com.hboxs.asl.dao.MemberDao;
import com.hboxs.asl.entity.Course;
import com.hboxs.asl.entity.Member;
import com.hboxs.asl.qcloudLVB.Conf;
import com.hboxs.asl.qcloudLVB.Constants;
import com.hboxs.asl.qcloudLVB.dao.LiveDao;
import com.hboxs.asl.qcloudLVB.entity.Live;
import com.hboxs.asl.qcloudLVB.service.LiveService;
import com.hboxs.asl.qcloudLVB.util.QcloudDateUtils;
import com.hboxs.asl.qcloudLVB.util.SafeUrlUtils;
import com.hboxs.asl.service.impl.BaseServiceImpl;
import com.hboxs.asl.wechat.utils.HttpClientUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;

/**
 * Service - 直播记录
 */
@Service("liveServiceImpl")
public class LiveServiceImpl extends BaseServiceImpl<Live, Long> implements LiveService {

    @Resource(name = "liveDaoImpl")
    private LiveDao liveDao;
    @Resource(name = "memberDaoImpl")
    private MemberDao memberDao;
    @Resource(name = "courseDaoImpl")
    private CourseDao courseDao;

    @Resource(name = "liveDaoImpl")
    public void setBaseDao(LiveDao liveDao) {
        super.setBaseDao(liveDao);
    }

    @Override
    public Boolean forbidden(Long id) {
        Live live = liveDao.find(id);
        if (live != null && !Live.LiveStatus.forbidden.equals(live.getLiveStatus())) {
            //远程关闭流
            Boolean b = changeStatus(0, id);
            if (!b) {
                return false;
            }
            //本地设置为禁播
            live.setLiveStatus(Live.LiveStatus.forbidden);
        }
        liveDao.merge(live);
        return true;
    }

    @Override
    public String getPushUrl(String bizId, String streamId, String key, Long txTime) {

        /*
         * 直播码
         */
        String livecode = bizId + "_" + streamId;

        /*
         * 防盗链
         */
        String safe = SafeUrlUtils.getSafeUrl(key, livecode, txTime);

        /*
         * 完整推流url : rtmp://4777.livepush.myqcloud.com/live/4777_641d6430ab?bizid=4777&txSecret=2fcc403c49eb72492df633f3b1537707&txTime=57FE5DFF
         */
        return "rtmp://" + bizId + ".livepush.myqcloud.com/live/" + livecode + "?bizid=" + bizId + safe;
    }


    @Override
    public Map<String, String> getPlayUrl(String bizId, String streamId) {

        /*
         * 直播码
         */
        String livecode = bizId + "_" + streamId;

        /*
         * 防盗链:不传key为空,需要传入时更改
         */
        String safe = SafeUrlUtils.getSafeUrl(null, livecode, null);

        String rtmp = "rtmp://" + bizId + ".liveplay.myqcloud.com/live/" + livecode + safe;
        String flv = "http://" + bizId + ".liveplay.myqcloud.com/live/" + livecode + ".flv" + safe;
        String m3u8 = "http://" + bizId + ".liveplay.myqcloud.com/live/" + livecode + ".m3u8" + safe;

        Map<String, String> map = new HashMap<>();
        map.put("rmtp", rtmp);
        map.put("flv", flv);
        map.put("m3u8", m3u8);

        return map;
    }

    @Override
    public Live create(Live live, Member anchor, Live connectLive) {
        live.setAnchor(anchor);
        //设置直播状态
        live.setLiveStatus(Live.LiveStatus.nolive);
        if( connectLive!=null){
            live.setConnectLiveId(connectLive.getId());
        }
        super.save(live);
        return live;
    }

    @Override
    public Boolean changeStatus(int status, Long liveId) {

        Live live = liveDao.find(liveId);

        Assert.notNull(live);

        Long t = QcloudDateUtils.getTxTime(Constants.API_CALL_TXTIME);

        JSONObject json = HttpClientUtils.get(
                Conf.API_CALL_URL + "?cmd=" + Conf.APPID + "&interface=" + "Live_Channel_SetStatus" + "&t=" + t.toString()
                        + "&sign=" + SafeUrlUtils.getSign(t) + "&Param.s.channel_id=" + Conf.BIZID + "_" + live.getId().toString()
                        + "&Param.n.status=" + String.valueOf(status)
        );

        String ret = String.valueOf(json.getInt("ret"));

        if ("0".equals(ret)) {
            //记录直播的状态
            live.setLiveStatus(status == 1 ? Live.LiveStatus.live : Live.LiveStatus.finished);
            //清空直播观看群集合
            live.getGroup().clear();
//            //记录播放总时间
//            Date now = new Date();
//            //转换为分钟
//            live.setTimeSpan((now.getTime() - live.getCreateDate().getTime()));
            liveDao.merge(live);
            return true;
        } else {
            return false;
        }

    }

    @Override
    public void changeCount(Member anchor, Member user, int type, int optype, int flag, String field) {

        //通过主播id查找live(直播)
        Live live = liveDao.findByAnchorAndStatus(anchor, Live.LiveStatus.live);

        if (flag == 0) {
            //直播
            //type==0:观看;type==1:点赞;type==2:收藏;optype==0:增加;optype==1:减少
            Set<Member> watches = live.getGroup();
            Set<Live> admires = user.getAdmireLives();
            Set<Live> favors = user.getFavorLives();

            //观看记录 不清除
            Set<Member> watchedMembers = live.getWatchedMembers();

            if (type == 0 && optype == 0) {
                //onetomany,由member维护,主播就是用户不进行增加
                if (anchor.equals(user)) {
                    return;
                }
                user.setWatchingLive(live);
                watchedMembers.add(user);
            } else if (type == 0 && optype == 1) {
                if (watches.size() != 0 && watches.contains(user)) {
                    user.setWatchingLive(null);
                }
            } else if (type == 1 && optype == 0) {
                admires.add(live);
            } else if (type == 1 && optype == 1) {
                if (admires.size() != 0 && admires.contains(live)) {
                    admires.remove(live);
                }
            } else if (type == 2 && optype == 0) {
                favors.add(live);
            } else if (type == 2 && optype == 1) {
                if (favors.size() != 0 && favors.contains(live)) {
                    favors.remove(live);
                }
            } else {
                return;
            }
            user.setAdmireLives(admires);
            user.setFavorLives(favors);
            memberDao.merge(user);
            liveDao.merge(live);

        }
    }

    /**
     * 主播下线清空正在观看的用户
     * @param live
     */
    @Override
    public void clearWatchingMembers(Live live) {
        Set<Member> memberSet = live.getGroup();
        if (memberSet.size() > 0) {
            for (Member member : memberSet) {
                member.setWatchingLive(null);
                memberDao.merge(member);
            }
        }
    }

    @Override
    public Page<Live> findPage(Pageable pageable, Live.LiveStatus liveStatus, Live.Type type) {

        return liveDao.findPage(pageable, liveStatus, type);
    }

    @Override
    public String getCOSSign(String bucketName, String cosPath) {
        return null;
    }

    @Override
    public Live findByAnchorAndStatus(Member anchor, Live.LiveStatus status) {
        return liveDao.findByAnchorAndStatus(anchor, Live.LiveStatus.live);
    }

    @Override
    public void evictDeadStream() {
        List<Filter> fs = new ArrayList<>();
        List<Course.CourseType> cs = new ArrayList<>();
        cs.add(Course.CourseType.live);
        cs.add(Course.CourseType.nolive);
        fs.add(Filter.in("courseType", cs));
        //筛选顺序
        List<Order> os = new ArrayList<>();
        os.add(Order.asc("createDate"));
        //每次查找20条数据
        List<Course> courses = courseDao.findListCommon(null, Constants.EVICT_LIVE_COUNT, fs, os);
        try {
            for (Course course : courses) {
                if (course.getLive() != null) {
                    JSONObject json = this.getStatus(course.getLive().getId());
                    if (json == null) {
                        //修改状态
                        course.getLive().setLiveStatus(Live.LiveStatus.finished);
                        liveDao.merge(course.getLive());
                        course.setCourseType(Course.CourseType.finished);
                        courseDao.merge(course);
                        continue;
                    }
                    int status = json.getInt("status");
                    //0：断流 3：关闭
                    if (status ==0 || status == 3) {
                        //修改状态
                        course.getLive().setLiveStatus(Live.LiveStatus.finished);
                        liveDao.merge(course.getLive());
                        course.setCourseType(Course.CourseType.finished);
                        courseDao.merge(course);
                    }
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void evictDeadStream2() {
        List<Filter> fs = new ArrayList<>();
        List<Live.LiveStatus> ls = new ArrayList<>();
        ls.add(Live.LiveStatus.live);
        ls.add(Live.LiveStatus.nolive);

        fs.add(Filter.in("liveStatus", ls));
        //帅选顺序
        List<Order> os = new ArrayList<>();
        os.add(Order.asc("createDate"));

        //每次查找20条记录
        List<Live> lives = liveDao.findListCommon(null, Constants.EVICT_LIVE_COUNT, fs, os);
        try {
            for (Live live : lives) {

                JSONObject json = this.getStatus(live.getId());
                if (json == null) {
                    live.setLiveStatus(Live.LiveStatus.finished);
                    liveDao.merge(live);
                    continue;
                }
                int status = json.getInt("status");
                //0为断流,3为关闭
                if (status == 0 || status == 3) {
                    live.setLiveStatus(Live.LiveStatus.finished);
                    liveDao.merge(live);
                }

            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public JSONObject getStatus(Long liveId) {

        Live live = liveDao.find(liveId);
        if (live == null || live.getAnchor() == null) {
            return null;
        }

        Long t = QcloudDateUtils.getTxTime(Constants.API_CALL_TXTIME);

        JSONObject output = null;

        try {

            JSONObject json = HttpClientUtils.get(
                    Conf.API_CALL_URL + "?cmd=" + Conf.APPID + "&interface=" + "Live_Channel_GetStatus" + "&t="
                            + t.toString() + "&sign=" + SafeUrlUtils.getSign(t) + "&Param.s.channel_id="
                            + Conf.BIZID + "_" + live.getId()

            );

            String ret = String.valueOf(json.getInt("ret"));

            if ("0".equals(ret)) {
                //返回查询到的直播推流状态
                output = json.getJSONArray("output").getJSONObject(0);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return output;
    }

    @Override
    public void offLive(Member anchor) {
        Live live = liveDao.offLive(anchor);
        if (live == null) {
            return;
        }
        this.changeStatus(0, live.getId());
    }

    @Override
    public void onLive(Member anchor) {
        liveDao.findByAnchorAndStatus(anchor, Live.LiveStatus.nolive);
    }

    @Override
    public void disConnect(Live live) {
        Live connectLive = liveDao.find(live.getConnectLiveId());
        if (connectLive==null) return;
        connectLive.setConnectLiveId(null);
        live.setConnectLiveId(null);
        save(connectLive);
        save(live);
    }

    @Override
    public List<Live> findConnectLive(Long connectLiveId) {
        return liveDao.findConnectLive(connectLiveId);
    }

    @Override
    public List<Live> findConnectLive(Long connectLiveId, Live.LiveStatus liveStatus) {
        return liveDao.findConnectLive(connectLiveId, liveStatus);
    }

    @Override
    public long getHostLiveCounts(Live.Type type) {
        return liveDao.getHostLiveCounts(type);
    }
}
